<?php

    /**
     * Compiler
     *
     * This is the compiler of configuration: it merges two INI file in a single array and stores it in a temporary file
     *
     * @package      Core
     * @subpackage   Config
     *
     * @license      GNU Lesser General Public Licence see LICENCE-LGPL file or http://www.gnu.org/licenses/lgpl.html
     */
    class Core_Config_Compiler
    {

	////////////////////////////////////////////////////////////////////////////
	//                             Static Methods                             //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Reads the given ini file. Merge it with the content of defaultconfig.ini.php
         * It also calculates some options. It stores the result in a temporary file
         *
         * @param		string          $filename : the name of the file in the config directory
		 * @param		string|null     $section
		 * @param		boolean|array	$config
		 * @throws		Core_ArgumentException
		 * @throws		Core_ArgumentNullException
		 * @throws		Core_IO_FileNotFoundException
         * @return      array   an object which contains configuration values
         */
        public static function get($filename, $section = null, $config = array('allowModifications' => true))
        {
            if ($filename === null) {
				throw new Core_ArgumentNullException('filename is a null reference');
			}

            if (strlen(trim($filename)) == 0) {
				throw new Core_ArgumentException('filename is a zero-length string');
			}

            $configfile    = Core_IO_Path::combine(PROJECT_CONFIG_PATH, $filename);
            
            if (!Core_IO_File::exists($configfile)) {
                throw new Core_IO_FileNotFoundException('Unable to find global configuration file ('. $filename .').');
            }

            $compile   = false;
			$configs   = array();
			$registry  = Zend_Registry::getInstance();
			$cachefile = Core_IO_Path::combine(PROJECT_TEMP_PATH, 'compiled', '~configs~');

            if (!Core_IO_File::exists($cachefile)) {
                $compile = true;
            } else {
                $cachefiletime = @filemtime($cachefile);
                $configfiletime = @filemtime($configfile);

                if ($configfiletime > $cachefiletime) {
                    $compile = true;
                } else {
                    foreach ($registry['modules'] as $module) {
                        $file = Core_IO_Path::combine($module, 'config.ini.php');

                        if (Core_IO_File::exists($file)) {
                            if (@filemtime($file) > $cachefiletime) {
                                $compile = true;
                                break;
                            }
                        }
                    }
                }
            }

            if ($compile) {
                if (!Core_IO_File::exists($configfile)) {
                    throw new Core_IO_FileNotFoundException('Unable to find global configuration file ('. $filename .').');
                }

                $configurations  = new Zend_Config_Ini($configfile, $section, $config);

                foreach ($registry['modules'] as $module) {
                    $file = Core_IO_Path::combine($module, 'config.ini.php');

                    if (Core_IO_File::exists($file)) {
                        if ($configurations instanceof Zend_Config) {
                            $configurations->merge(new Zend_Config_Ini($file, $section, $config));
                        }
                    }
                }

                $configs = $configurations->toArray();
                Core_IO_File::writeAll($cachefile, var_export($configs, true));
            } else {
                $str = Core_IO_File::readAll($cachefile);
                $configs = eval('return '. $str .';');
            }

            return $configs;
        }
    }
